

import os
import re
import sys
import csv
import json
from datetime import timedelta
import requests

from quantway.common.settings import ROOT_CONF

class Param(dict):
    ''' 用来处理配置文件
        object is like a dictionary except `obj.foo` can be used
        in addition to `obj['foo']`.
    
        >>> o = DottedDict(a=1)
        >>> o.a
        1
        >>> o['a']
        1
        >>> o.a = 2
        >>> o['a']
        2
        >>> del o.a
        >>> o.a
        Traceback (most recent call last):
            ...
        AttributeError: 'a'
    '''
    def __getattr__(self, key):
        try:
            return self[key]
        except KeyError as k:
            raise AttributeError(k)

    def __setattr__(self, key, value):
        self[key] = value
    def __delattr__(self, key):
        try:
            del self[key]
        except KeyError as k:
            raise AttributeError(k)

    def __repr__(self):
        return '<Param ' + dict.__repr__(self) + '>'
    



def read_jsonparam(confpath):
    f = open(confpath,'r')
    txt = f.read()
    f.close()
    return __make_param(json.loads(txt))


def __make_param(di):
    '''
        recursivly make Param
    '''
    for key in di:
        if isinstance(di[key], dict):
            di[key] = __make_param(di[key])
    return Param(di)



def split_list_by_num(codelist, num_piece):
    piece = len(codelist)//num_piece
    extra = len(codelist) % num_piece   
    split = [codelist[i*piece:(i+1)*piece] for i in range(num_piece)]
    if extra != 0:
        for i in range(extra):
            split[i].append(codelist[ num_piece*piece + i ])
    return split



def get_codelist(codelist_name):
    with open(os.path.join(ROOT_CONF, "code", codelist_name+".csv"), "r") as f:
        reader = csv.reader(f)
        return [ r[0]  for r in reader]
    


def get_codelist_from_lst(lst_path, sort=True):
    ''' 从当前运行的进程相同目录下的conf文件中读取codelist.lst中的所有代码列表文件中的代码。
        codelist.lst中一行代表一个代码列表文件
        可以用#来注释

        lst_path : codelist file path
        sort : if True, sort code list sh first and sz later.

        返回：一个所有代码列表文件中所有代码的并集
    '''
    with open(lst_path, "r") as f:
        lines = f.read().strip().split(os.linesep)
    set_codelist = set()
    for line in lines:
        if line.startswith("#"):        # 注释掉的就不要读入
            continue
        else:
            set_codelist.update(get_codelist(line))
    
    if sort:
        code_list = list(set_codelist)
        code_list.sort()
        return code_list
    else:
        return list(set_codelist)


def is_valid_stockcode(code):
    ''' 此函数判断是否合法的代码 ， 含指数
        沪市代码以sh开头，第一位第二位是60，第三位到第六位从0001-9999
        深市代码以sz开头，第一位第二位是00，或者30，然后第三位到第六位从0001-9999
        以sh开头的要用到的指数有sh000001
        以sz开头的要用到的指数有sz399001,sz399300,sz399005,sz399006
    '''
    if re.match(r'sh[6][80]\d{4}|sz[03][0]\d{4}', code) is None:
        sys.stderr.write("%s is not a valid stock code!\n" % code)
        return False
    return True


def next_date(d):
    ''' param d  given date
        return the next date regarding to given date
    '''
    return d+timedelta(days=1)





def get_module_name():
    '''
        获取模块名称，比如
    '''
    mod = sys.modules['__main__']  
    file = getattr(mod, '__file__', None)  
    return os.path.splitext(os.path.basename(file))[0]
